<?php
require_once 'Console/Color.php';

class NoBusinessBase_Utility_Status extends ArrayObject
{
   const STATUS_OK            = 0x00000000;
   const STATUS_INFO          = 0x00000001;
   const STATUS_WAITING       = 0x00000010;
   const STATUS_WARNING       = 0x00000100;
   const STATUS_BAD           = 0x00001000;
   // Left some space
   const STATUS_DEV_ERROR     = 0x01000000;
   const STATUS_UNAUTHORIZED  = 0x10000000;

   private $_children                     = array();
   private $_extraInfo                    = array();
   private $_message                      = '';
   private $_pParent                      = null;
   private $_statusCode                   = 0x0;
   private $_status                       = self::STATUS_OK;
   private $_setHttResponseCodeOnInvoke   = true;

   public function __construct($status = self::STATUS_OK, $message = '', $throwException = false)
   {
      $this->setStatus($status);
      $this->setMessage($message);
      if($throwException)
         throw(new NoBusinessBase_Exception_Status($this));
   }

   public function __destruct()
   {
      // remove reference to parent
      unset($this->_pParent);

      // remove references to children;
      foreach($this->_children as $pChildStatus)
      {
         unset($pChildStatus);
      }
   }

/************************************************************************/
/* Interface                                                            */
/************************************************************************/

   public function addChildStatus(NoBusinessBase_Utility_Status $pStatus)
   {
      $this->_children[] = $pStatus;
   }

   public function throwException($minimum = self::STATUS_OK)
   {
      $value = $this->getChildrenStatus();
      if($value >= $minimum)
         throw(new NoBusinessBase_Exception_Status($this));
   }

/************************************************************************/
/* Magic Funtions                                                       */
/************************************************************************/

   public function toJson()
   {
      return $this();
   }

   public function __get($varName)
   {
      if(!isset($this->_extraInfo[$varName]))
         return null;
      return $this->_extraInfo[$varName];
   }

   public function __set($varName, $value)
   {
      $this->_extraInfo[$varName] = $value;
   }

   public function __invoke()
   {
      $childStatuses = array();
      foreach($this->_children as $pChildState)
      {
         $pChildState->setHttResponseCodeOnInvoke($this->_setHttResponseCodeOnInvoke);
         $childStatuses[] = $pChildState();
      }

      $asArray = array(
         'status'          => $this->getStatusAsString(),
         'statusValue'     => $this->_status,
         'statusCode'      => $this->_statusCode,
         'childrenStatus'  => $this->getChildrenStatusAsString(),
         'message'         => $this->_message,
         'extraInfo'       => $this->_extraInfo,
         'childStatuses'   => $childStatuses
      );

      //$pJsonHelper = new Zend_View_Helper_Json();
      $response = Zend_Controller_Front::getInstance()->getResponse();
      if($this->_setHttResponseCodeOnInvoke === true)
      {
         $childrenStatus = self::getChildrenStatus();
         switch($childrenStatus)
         {
            case self::STATUS_OK: $response->setHttpResponseCode(200); break;
            case self::STATUS_UNAUTHORIZED: $response->setHttpResponseCode(401); break;
            case self::STATUS_INFO: $response->setHttpResponseCode(401); break;
         }
      }
      return $asArray;
   }

   public function __toString()
   {
      return $this->_message;
   }

   public function offsetSet($index, $value)
   {
      if($value == null)
      {
         trigger_error("Can not set a child status to NULL");
      }
      // Only allow status append of this type of class
      if(get_class($value) != get_class($this))
         return;
      
      if($index === null)
         $this->_children[] = $value;
      else
         $this->_children[$index] = $value;
   }

/************************************************************************/
/* Getters / Setters                                                    */
/************************************************************************/

   // Status
   public function getStatus()
   {
      return $this->_status;
   }
   public function setStatus($status, $message = null)
   {
      $this->_status = $status;
      $this->setMessage($message);
   }

   // Message
   public function getMessage()
   {
      return $this->_message;
   }
   public function setMessage($message)
   {
      if(is_string($message))
         $this->_message = $message;
   }


   // _setHttResponseCodeOnInvoke
   public function setHttResponseCodeOnInvoke($rhs)
   {
      $this->_setHttResponseCodeOnInvoke  = $rhs;
   }
   
/************************************************************************/
/* Static Utilites                                                      */
/************************************************************************/

   static public function statusAsString($status)
   {
      switch($status)
      {
         case self::STATUS_DEV_ERROR:     return 'Developer Error';
         case self::STATUS_BAD:           return 'Bad';
         case self::STATUS_INFO:          return 'Info';
         case self::STATUS_WARNING:       return 'Warning';
         case self::STATUS_WAITING:       return 'Waiting';
         case self::STATUS_UNAUTHORIZED:  return 'Unauthorized';
      }
      return 'OK';
   }

   static public function statusAsColorString($status)
   {
      switch($status)
      {
         case self::STATUS_DEV_ERROR:     return Console_Color::convert('%rDeveloper Error%n');
         case self::STATUS_BAD:           return Console_Color::convert('%rBad%n');
         case self::STATUS_INFO:          return Console_Color::convert('%bInfon');
         case self::STATUS_WARNING:       return Console_Color::convert('%yWarning%n');
         case self::STATUS_WAITING:       return Console_Color::convert('%mWaiting%n');
         case self::STATUS_UNAUTHORIZED:  return Console_Color::convert('%rUnauthorized%n');
      }
      return Console_Color::convert('%gOK%n');
   }

/************************************************************************/
/* Utilites                                                             */
/************************************************************************/

   public function getStatusAsString()
   {
      return self::statusAsString($this->_status);
   }

   public function getStatusAsColorString()
   {
      return self::statusAsColorString($this->_status);
   }

   public function getChildrenStatus()
   {
      $worstStatus = self::STATUS_OK;
      if(count($this->_children) == 0)
         return $this->getStatus();
      foreach($this->_children as $pChildState)
      {
         $status = $pChildState->getChildrenStatus();
         if($status > $worstStatus)
            $worstStatus = $status;
      }
      return $worstStatus;
   }

   public function getChildrenStatusAsString()
   {
      return self::statusAsString(self::getChildrenStatus());
   }

   public function getAllMessagesAboveStatusMinimum($minimum)
   {
      $messages = array();

      if($this->getStatus() > $minimum)
         $messages[] = $this->getMessage();

      foreach($this->_children as $pChildState)
      {
         $messages = array_merge($messages, $pChildState->getAllMessagesAboveStatusMinimum($minimum));
      }

      return $messages;
   }

   public function getAllStatusesAboveStatusMinimum($minimum)
   {
      $statuses = array();

      if($this->getStatus() > $minimum)
         $statuses[] = $this;

      foreach($this->_children as $pChildState)
      {
         $statuses = array_merge($statuses, $pChildState->getAllStatusesAboveStatusMinimum($minimum));
      }

      return $statuses;
   }

   public function consolePrint($minimum = self::STATUS_OK)
   {
      $ret = $this->getAllStatusesAboveStatusMinimum($minimum);
      foreach($ret as $indiv)
         echo $indiv->getStatusAsColorString() . ": " . $indiv->getMessage() . PHP_EOL;
   }

/************************************************************************/
/* Helpers                                                              */
/************************************************************************/
}

